package com.wsm.web.exeception;


import com.wsm.common.ErrorEnums;
import com.wsm.common.Result;
import javassist.NotFoundException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.management.openmbean.KeyAlreadyExistsException;
import javax.servlet.http.HttpServletRequest;


@ControllerAdvice
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {
    @ExceptionHandler
    public Result<?> systemExceptionHandler(RuntimeException e) {
        printlnStackTrace(e);
        return Result.error(e.getMessage(), ErrorEnums.SYSTEM_ERROR.getCode());
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<Result<?>> defaultExceptionHandler(HttpServletRequest request, Exception e) {
        printlnStackTrace(e);
        Integer code;
        String message;
        if (e instanceof IllegalStateException) {
            code = ErrorEnums.CHECK_FAIL_MSG.getCode();
            message = ErrorEnums.CHECK_FAIL_MSG.getMsg() + "(" + request.getServletPath() + ")";
        } else if (e instanceof NoHandlerFoundException) {
            code = ErrorEnums.CANNOT_FOUND_ERROR.getCode();
            message = ErrorEnums.CANNOT_FOUND_ERROR.getMsg() + "(" + request.getServletPath() + ")";
        } else if (e instanceof MissingServletRequestParameterException) {
            MissingServletRequestParameterException msrpe = (MissingServletRequestParameterException) e;
            code = ErrorEnums.MISSING_PARAMETER.getCode();
            message = ErrorEnums.MISSING_PARAMETER.getMsg() + "(" + msrpe.getParameterName() + ")";
        } else if (e instanceof MethodArgumentTypeMismatchException) {
            MethodArgumentTypeMismatchException matme = (MethodArgumentTypeMismatchException) e;
            code = ErrorEnums.ARG_TYPE_MISMATCH.getCode();
            message = ErrorEnums.ARG_TYPE_MISMATCH.getMsg() + "(" + matme.getParameter().getParameterName() + ")";
        } else if (e instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException manve = (MethodArgumentNotValidException) e;
            code = ErrorEnums.ARG_TYPE_MISMATCH.getCode();
            FieldError error = (FieldError) manve.getBindingResult().getAllErrors().get(0);
            StringBuilder buffer = new StringBuilder();
            message = buffer.append(ErrorEnums.ARG_TYPE_MISMATCH.getMsg()).append("(").append("参数名: ").append(error.getField())
                    .append(", 错误信息: ").append(error.getDefaultMessage()).append(")").toString();
        } else if (e instanceof NotFoundException) {
            code = ErrorEnums.DATA_NOT_EXISTS.getCode();
            message = ErrorEnums.DATA_NOT_EXISTS.getMsg() + "(" + e.getMessage() + ")";
        } else if (e instanceof KeyAlreadyExistsException) {
            code = ErrorEnums.DATA_IS_EXISTS.getCode();
            message = ErrorEnums.DATA_IS_EXISTS.getMsg() + "(" + e.getMessage() + ")";
        } else {
            code = ErrorEnums.INTERNAL_ERROR.getCode();
            message = ErrorEnums.INTERNAL_ERROR + "(" + e.getMessage() + ")";
        }
        Result<?> error = Result.error(message, code);
        return ResponseEntity.status(code).body(error);
    }

    /**
     * 打印异常堆栈信息
     *
     * @param e
     */
    private void printlnStackTrace(Exception e) {
        String logError = "\n********************************" +
                "\n异常类型: " + e.getClass() +
                "\n异常信息: " + e.getMessage();
        if (log.isTraceEnabled()) {
            logError += "\n" + ExceptionUtils.getStackTrace(e);
        }
        logError += "\n" + "********************************";
        log.error(logError);
    }
}
